package com.yuzhi.master.pump.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.yuzhi.master.drainFaultManagement.domain.DrainFaultManagement;
import com.yuzhi.master.drainFaultManagement.mapper.DrainFaultManagementMapper;
import com.yuzhi.master.pump.domain.DrainPumpBj;
import com.yuzhi.master.pump.domain.DrainSewageQf;
import com.yuzhi.master.pump.mapper.DrainPumpBjMapper;
import com.yuzhi.master.pump.mapper.DrainSewageQfMapper;
import com.yuzhi.master.pump.service.IDrainPumpBjService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 排水泵机Service业务层处理
 *
 * @author auto code generator
 * @date 2025-08-18
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DrainPumpBjServiceImpl implements IDrainPumpBjService {

    private final DrainPumpBjMapper baseMapper;

    private final DrainSewageQfMapper drainSewageQfMapper;

    private final DrainFaultManagementMapper drainFaultManagementMapper;

    /**
     * 物联网推送数据保存泵机运行信息
     *
     * @param msg
     */
    @Override
    public void saveBjMessage(String deviceId, String msg) {
        // 1.解析JSON数据对象
        JSONObject json = JSONObject.parseObject(msg);
        String deviceIds = json.getString("deviceId");
        JSONObject payload = json.getJSONObject("payload");
        // 健壮性判断
        if (payload == null) {
            log.error("payload参数为空，暂不处理");
            return;
        }
        // 获取通用水位值（water_level，没有下划线后缀的）
        BigDecimal generalWaterLevel = payload.getBigDecimal("water_level");
        // 获取payload中的QF1的key是否存在
        if (payload.containsKey("QF1") && payload.get("QF1") != null) {
            DrainSewageQf entity = new DrainSewageQf();

            // 采集时间
            Long ts = json.getLong("timestamp");
            LocalDateTime timestamp = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts), ZoneId.systemDefault());
            entity.setCjDate(timestamp);

            // QF1 / QF2
            Double qf1 = payload.getDouble("QF1");
            Double qf2 = payload.getDouble("QF2");
            entity.setQfOne(qf1 != null ? qf1.toString() : null);
            entity.setQfTow(qf2 != null ? qf2.toString() : null);

            // QF1 + QF2
            if (qf1 != null || qf2 != null) {
                double sum = (qf1 == null ? 0 : qf1) + (qf2 == null ? 0 : qf2);
                entity.setQfSum(BigDecimal.valueOf(sum).toPlainString());
            }

            // flow_total
            Double ft1 = payload.getDouble("flow_total_1");
            Double ft2 = payload.getDouble("flow_total_2");
            Double ft3 = payload.getDouble("flow_total_3");
            Double ft4 = payload.getDouble("flow_total_4");
            entity.setFlowTotalOne(ft1 != null ? ft1.toString() : null);
            entity.setFlowTotalTow(ft2 != null ? ft2.toString() : null);
            entity.setFlowTotalThree(ft3 != null ? ft3.toString() : null);
            entity.setFlowTotalFour(ft4 != null ? ft4.toString() : null);

            if (ft1 != null || ft2 != null || ft3 != null || ft4 != null) {
                double totalSum = (ft1 == null ? 0 : ft1)
                        + (ft2 == null ? 0 : ft2)
                        + (ft3 == null ? 0 : ft3)
                        + (ft4 == null ? 0 : ft4);
                // 避免科学计数法
                entity.setFlowTotalSum(BigDecimal.valueOf(totalSum).toPlainString());

            }
            // flow_in
            Double fi1 = payload.getDouble("flow_in_1");
            Double fi2 = payload.getDouble("flow_in_2");
            Double fi3 = payload.getDouble("flow_in_3");
            Double fi4 = payload.getDouble("flow_in_4");
            entity.setFlowInOne(fi1 != null ? fi1.toString() : null);
            entity.setFlowInTow(fi2 != null ? fi2.toString() : null);
            entity.setFlowInThree(fi3 != null ? fi3.toString() : null);
            entity.setFlowInFour(fi4 != null ? fi4.toString() : null);

            if (fi1 != null || fi2 != null || fi3 != null || fi4 != null) {
                double inSum = (fi1 == null ? 0 : fi1)
                        + (fi2 == null ? 0 : fi2)
                        + (fi3 == null ? 0 : fi3)
                        + (fi4 == null ? 0 : fi4);
                // 避免科学计数法
                entity.setFlowInSum(BigDecimal.valueOf(inSum).toPlainString());
            }

            // factId 和 fkType 可以根据 deviceId 解析或外部传入（这里暂时留空）
            entity.setFactId(deviceId);
            entity.setFkType((short) 2); // 例如默认泵站
            // 泵站液位 - 修复空指针异常，添加null检查
            if (generalWaterLevel != null) {
                entity.setWaterLevel(generalWaterLevel.toString());
            } else {
                log.warn("设备 {} 的消息中未包含通用水位值(water_level)", deviceId);
                entity.setWaterLevel(null); // 或者设置默认值
            }
            // 插入数据库
            drainSewageQfMapper.insert(entity);
            log.info("成功保存总功率实时数据, deviceId={}", deviceId);

        } else {
            // 调用泵机运行处理方法继续处理
            savePumpBjSz(deviceId, json);
        }
    }


    @Override
    public void savePumpBjSz(String deviceId, JSONObject json) {
        log.info("开始处理泵机数据保存, deviceId={}", deviceId);
        try {
            JSONObject payload = json.getJSONObject("payload");
            // 解析时间戳为LocalDateTime
            Long timestamp = json.getLong("timestamp");
            LocalDateTime dateTime = LocalDateTime.ofInstant(
                    Instant.ofEpochMilli(timestamp),
                    ZoneId.systemDefault()
            );
            // 解析 payload 中包含 BengRun 和 BengFault 的键值对
            Map<String, Boolean> bengRunMap = new HashMap<>();
            Map<String, Boolean> bengFaultMap = new HashMap<>();
            Map<String, BigDecimal> waterLevel = new HashMap<>();
            Map<String, BigDecimal> flowIn = new HashMap<>();
            Map<String, BigDecimal> flowTotal = new HashMap<>();

            // 获取通用水位值（water_level，没有下划线后缀的）
            BigDecimal generalWaterLevel = payload.getBigDecimal("water_level");

            for (String key : payload.keySet()) {
                if (key.startsWith("BengRun_")) {
                    String pumpNumber = key.substring("BengRun_".length());
                    Boolean isRunning = payload.getBoolean(key);
                    bengRunMap.put(pumpNumber, isRunning);
                } else if (key.startsWith("BengFault_")) {
                    String pumpNumber = key.substring("BengFault_".length());
                    Boolean isFault = payload.getBoolean(key);
                    bengFaultMap.put(pumpNumber, isFault);
                } else if (key.startsWith("water_level_")) {
                    String pumpNumber = key.substring("water_level_".length());
                    BigDecimal waterLevelValue = payload.getBigDecimal(key);
                    waterLevel.put(pumpNumber, waterLevelValue);
                } else if (key.startsWith("flow_in_")) {
                    String flowInNumber = key.substring("flow_in_".length());
                    BigDecimal flowInValue = payload.getBigDecimal(key);
                    flowIn.put(flowInNumber, flowInValue);
                } else if (key.startsWith("flow_total_")) {
                    String flowTotalNumber = key.substring("flow_total_".length());
                    BigDecimal flowTotalValue = payload.getBigDecimal(key);
                    flowTotal.put(flowTotalNumber, flowTotalValue);
                }
            }
            // 处理每个泵机的数据
            for (String pumpNumber : bengRunMap.keySet()) {
                try {
                    Boolean isRunning = bengRunMap.get(pumpNumber);
                    Boolean isFault = bengFaultMap.getOrDefault(pumpNumber, false);
                    // 优先获取特定泵机的水位值，如果没有则使用通用水位值
                    BigDecimal waterLevelValue = waterLevel.get(pumpNumber);
                    if (waterLevelValue == null) {
                        waterLevelValue = generalWaterLevel;
                    }
                    // 查询该泵机的最新状态
                    DrainPumpBj latestBj = baseMapper.selectLatestByPumpBjId(deviceId, pumpNumber);
                    DrainPumpBj drainPumpBj = new DrainPumpBj();
                    drainPumpBj.setPumpId(deviceId);
                    drainPumpBj.setPumpBjId(pumpNumber);
                    drainPumpBj.setMName(pumpNumber);
                    drainPumpBj.setSort(pumpNumber.indexOf(pumpNumber));
                    drainPumpBj.setFault(isFault);
                    // 修复空指针异常，添加null检查
                    if (waterLevelValue != null) {
                        drainPumpBj.setWaterLevel(waterLevelValue.toString());
                    } else {
                        log.warn("设备 {} 泵机 {} 未获取到水位值", deviceId, pumpNumber);
                        drainPumpBj.setWaterLevel(null); // 或者设置默认值
                    }

                    //drainPumpBj.setSort(pumpNumber.codePointAt(pumpNumber.length()-1));
                    drainPumpBj.setCjTime(dateTime);
                    drainPumpBj.setState(isRunning ? 1 : 0);
                    //判断泵机是否故障
                    if (isFault){
                        DrainFaultManagement drainFaultManagement = new DrainFaultManagement();
                        drainFaultManagement.setFaultTitle(pumpNumber+"号泵故障");
                        drainFaultManagement.setFaultSource(json.getString("deviceId"));
                        drainFaultManagement.setDeviceType("2");
                        drainFaultManagement.setDeviceCode(deviceId);
                        drainFaultManagement.setFaultLevel("2");
                        drainFaultManagement.setFaultType("5");
                        drainFaultManagement.setFaultState("1");
                        drainFaultManagement.setFaultOccurrenceTime(dateTime);
                        drainFaultManagement.setFaultContent(pumpNumber+"号泵故障");
                        drainFaultManagementMapper.insert(drainFaultManagement);
                    }
                    // 状态变化检测逻辑
                    if (latestBj != null) {
                        // 有历史记录，比较状态变化
                        Integer lastState = latestBj.getState();
                        Integer currentState = isRunning ? 1 : 0;
                        if (!currentState.equals(lastState)) {
                            // 状态发生变化
                            if (currentState == 1) {
                                // 从关闭变为开启，设置开启时间
                                drainPumpBj.setStartTime(dateTime);
                                // 保持上次的关闭时间
                                //drainPumpBj.setCloseTime(latestBj.getCloseTime());
                            } else {
                                // 从开启变为关闭，设置关闭时间
                                drainPumpBj.setCloseTime(dateTime);
                                // 保持上次的开启时间
                                //drainPumpBj.setStartTime(latestBj.getStartTime());
                            }
                        } else {
                            // 状态未变化，保持历史时间
                            drainPumpBj.setStartTime(latestBj.getStartTime());
                            drainPumpBj.setCloseTime(latestBj.getCloseTime());
                        }
                    } else {
                        // 没有历史记录，根据当前状态设置时间
                        if (isRunning) {
                            drainPumpBj.setStartTime(dateTime);
                        } else {
                            drainPumpBj.setCloseTime(dateTime);
                        }
                    }
                    // 保存到数据库
                    int result = baseMapper.insert(drainPumpBj);
                    if (result > 0) {
                        log.info("泵机数据保存成功, deviceId={}, pumpNumber={}, state={}, fault={}, waterLevel={}",
                                deviceId, pumpNumber,
                                isRunning ? "开启" : "关闭",
                                isFault ? "故障" : "正常",
                                waterLevelValue);
                    } else {
                        log.error("泵机数据保存失败, deviceId={}, pumpNumber={}", deviceId, pumpNumber);
                    }
                } catch (Exception e) {
                    log.error("处理单个泵机数据时发生异常, deviceId={}, pumpNumber={}, error={}",
                            deviceId, pumpNumber, e.getMessage(), e);
                }
            }
            log.info("泵机数据保存处理完成, deviceId={}, 处理泵机数量={}",
                    deviceId, bengRunMap.size());
        } catch (Exception e) {
            log.error("处理泵机数据保存时发生异常, deviceId={}, error={}", deviceId, e.getMessage(), e);
        }
    }

    @Override
    public void monitoringAnalysis(String deviceSn, String decodedResponse) {
        JSONObject decodedResponseJson = JSONObject.parseObject(decodedResponse);
        JSONObject resultJson = decodedResponseJson.getJSONObject("result");
        // 解析 COLLECT_TIME: 支持毫秒时间戳或字符串时间
        LocalDateTime collectTime;
        Object collectRaw = resultJson.get("COLLECT_TIME");
        if (collectRaw == null) {
            collectTime = LocalDateTime.now();
        } else if (collectRaw instanceof Number) {
            long ts = ((Number) collectRaw).longValue();
            try {
                collectTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts), ZoneId.systemDefault());
            } catch (Exception e) {
                log.warn("COLLECT_TIME(毫秒) 解析失败, 使用当前时间, 原始值={}, error={}", ts, e.getMessage());
                collectTime = LocalDateTime.now();
            }
        } else {
            String collectTimeStr = String.valueOf(collectRaw);
            try {
                collectTime = LocalDateTime.parse(collectTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            } catch (Exception e) {
                log.warn("COLLECT_TIME(字符串) 解析失败, 使用当前时间, 原始值={}, error={}", collectTimeStr, e.getMessage());
                collectTime = LocalDateTime.now();
            }
        }

        // 遍历 result 下的每个设备节点 (排除 COLLECT_TIME)
        for (String nodeKey : resultJson.keySet()) {
            if ("COLLECT_TIME".equals(nodeKey)) {
                continue;
            }
            JSONObject node = resultJson.getJSONObject(nodeKey);
            if (node == null) {
                continue;
            }
            // 收集带下划线后缀的键值
            Map<String, Boolean> bengRunMap = new HashMap<>();
            Map<String, Boolean> bengFaultMap = new HashMap<>();
            Map<String, BigDecimal> waterLevelMap = new HashMap<>();
            Map<String, BigDecimal> flowInMap = new HashMap<>();
            Map<String, BigDecimal> flowTotalMap = new HashMap<>();

            BigDecimal generalWaterLevel = node.getBigDecimal("water_level");
            Double qf1 = node.getDouble("QF1");
            Double qf2 = node.getDouble("QF2");

            Double ft1 = null, ft2 = null, ft3 = null, ft4 = null;
            Double fi1 = null, fi2 = null, fi3 = null, fi4 = null;

            for (String key : node.keySet()) {
                if (key.startsWith("BengRun_")) {
                    String suffix = key.substring("BengRun_".length());
                    bengRunMap.put(suffix, node.getBoolean(key));
                } else if (key.startsWith("BengFault_")) {
                    String suffix = key.substring("BengFault_".length());
                    bengFaultMap.put(suffix, node.getBoolean(key));
                } else if (key.startsWith("water_level_")) {
                    String suffix = key.substring("water_level_".length());
                    waterLevelMap.put(suffix, node.getBigDecimal(key));
                } else if (key.startsWith("flow_in_")) {
                    String suffix = key.substring("flow_in_".length());
                    BigDecimal v = node.getBigDecimal(key);
                    flowInMap.put(suffix, v);
                    // 同时尝试提取 1~4 的常用位
                    if ("1".equals(suffix)) fi1 = v == null ? null : v.doubleValue();
                    if ("2".equals(suffix)) fi2 = v == null ? null : v.doubleValue();
                    if ("3".equals(suffix)) fi3 = v == null ? null : v.doubleValue();
                    if ("4".equals(suffix)) fi4 = v == null ? null : v.doubleValue();
                } else if (key.startsWith("flow_total_")) {
                    String suffix = key.substring("flow_total_".length());
                    BigDecimal v = node.getBigDecimal(key);
                    flowTotalMap.put(suffix, v);
                    if ("1".equals(suffix)) ft1 = v == null ? null : v.doubleValue();
                    if ("2".equals(suffix)) ft2 = v == null ? null : v.doubleValue();
                    if ("3".equals(suffix)) ft3 = v == null ? null : v.doubleValue();
                    if ("4".equals(suffix)) ft4 = v == null ? null : v.doubleValue();
                }
            }

            // 写入总量/进量/QF 等信息
            if (qf1 != null || qf2 != null ||
                    !flowTotalMap.isEmpty() || !flowInMap.isEmpty()) {
                DrainSewageQf entity = new DrainSewageQf();
                entity.setCjDate(collectTime);
                entity.setQfOne(qf1 != null ? qf1.toString() : null);
                entity.setQfTow(qf2 != null ? qf2.toString() : null);
                if (qf1 != null || qf2 != null) {
                    double s = (qf1 == null ? 0 : qf1) + (qf2 == null ? 0 : qf2);
                    entity.setQfSum(BigDecimal.valueOf(s).toPlainString());
                }

                // 仅提取 1~4 位的常见字段，保持与现有表结构一致
                entity.setFlowTotalOne(ft1 != null ? ft1.toString() : null);
                entity.setFlowTotalTow(ft2 != null ? ft2.toString() : null);
                entity.setFlowTotalThree(ft3 != null ? ft3.toString() : null);
                entity.setFlowTotalFour(ft4 != null ? ft4.toString() : null);
                if (ft1 != null || ft2 != null || ft3 != null || ft4 != null) {
                    double totalSum = (ft1 == null ? 0 : ft1)
                            + (ft2 == null ? 0 : ft2)
                            + (ft3 == null ? 0 : ft3)
                            + (ft4 == null ? 0 : ft4);
                    entity.setFlowTotalSum(BigDecimal.valueOf(totalSum).toPlainString());
                }

                entity.setFlowInOne(fi1 != null ? fi1.toString() : null);
                entity.setFlowInTow(fi2 != null ? fi2.toString() : null);
                entity.setFlowInThree(fi3 != null ? fi3.toString() : null);
                entity.setFlowInFour(fi4 != null ? fi4.toString() : null);
                if (fi1 != null || fi2 != null || fi3 != null || fi4 != null) {
                    double inSum = (fi1 == null ? 0 : fi1)
                            + (fi2 == null ? 0 : fi2)
                            + (fi3 == null ? 0 : fi3)
                            + (fi4 == null ? 0 : fi4);
                    entity.setFlowInSum(BigDecimal.valueOf(inSum).toPlainString());
                }

                entity.setFactId(deviceSn);
                entity.setFkType((short) 2);
                if (generalWaterLevel != null) {
                    entity.setWaterLevel(generalWaterLevel.toString());
                }
                drainSewageQfMapper.insert(entity);
                log.info("监测数据-累计/进量/QF已保存, deviceSn={}, node={}", deviceSn, nodeKey);
            }

            // 写入各泵运行/故障/水位，按循环次数设置排序(第一次为1)
            for (String pumpNum : bengRunMap.keySet()) {
                try {
                    Boolean isRunning = bengRunMap.get(pumpNum);
                    Boolean isFault = bengFaultMap.getOrDefault(pumpNum, false);
                    BigDecimal pumpWaterLevel = waterLevelMap.get(pumpNum);
                    if (pumpWaterLevel == null) {
                        pumpWaterLevel = generalWaterLevel;
                    }

                    DrainPumpBj latestBj = baseMapper.selectLatestByPumpBjId(deviceSn, pumpNum);

                    DrainPumpBj record = new DrainPumpBj();
                    record.setPumpId(deviceSn);
                    record.setPumpBjId(pumpNum);
                    record.setMName(pumpNum);
                    // 根据循环次数设置排序: 第一次循环为1
                    record.setSort(Integer.parseInt(pumpNum));
                    record.setFault(isFault);
                    // 每泵瞬时流量与累计流量
                    BigDecimal pumpFlowIn = flowInMap.get(pumpNum);
                    BigDecimal pumpFlowTotal = flowTotalMap.get(pumpNum);
                    record.setFlowIn(pumpFlowIn);
                    record.setFlowTotal(pumpFlowTotal);
                    record.setWaterLevel(pumpWaterLevel == null ? null : pumpWaterLevel.toString());
                    record.setCjTime(collectTime);
                    record.setState(Boolean.TRUE.equals(isRunning) ? 1 : 0);

                    if (Boolean.TRUE.equals(isFault)) {
                        DrainFaultManagement fm = new DrainFaultManagement();
                        fm.setFaultTitle(pumpNum + "号泵故障");
                        fm.setFaultSource(nodeKey);
                        fm.setDeviceType("2");
                        fm.setDeviceCode(deviceSn);
                        fm.setFaultLevel("2");
                        fm.setFaultType("5");
                        fm.setFaultState("1");
                        fm.setFaultOccurrenceTime(collectTime);
                        fm.setFaultContent(pumpNum + "号泵故障");
                        drainFaultManagementMapper.insert(fm);
                    }

                    if (latestBj != null) {
                        Integer lastState = latestBj.getState();
                        Integer currentState = Boolean.TRUE.equals(isRunning) ? 1 : 0;
                        if (!currentState.equals(lastState)) {
                            if (currentState == 1) {
                                record.setStartTime(collectTime);
                            } else {
                                record.setCloseTime(collectTime);
                            }
                        } else {
                            record.setStartTime(latestBj.getStartTime());
                            record.setCloseTime(latestBj.getCloseTime());
                        }
                    } else {
                        if (Boolean.TRUE.equals(isRunning)) {
                            record.setStartTime(collectTime);
                        } else {
                            record.setCloseTime(collectTime);
                        }
                    }

                    int res = baseMapper.insert(record);
                    if (res > 0) {
                        log.info("监测数据-泵机保存成功 deviceSn={}, node={}, pump={}, state={}, fault={}",
                                deviceSn, nodeKey, pumpNum,
                                Boolean.TRUE.equals(isRunning) ? "开启" : "关闭",
                                Boolean.TRUE.equals(isFault) ? "故障" : "正常");
                    }
                } catch (Exception ex) {
                    log.error("保存泵机监测数据异常 deviceSn={}, node={}, pump={}, error={}",
                            deviceSn, nodeKey, pumpNum, ex.getMessage(), ex);
                }
            }
        }
    }
}
